package aupdg.presentation;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.processmining.framework.log.AuditTrailEntry;
import org.processmining.framework.log.AuditTrailEntryList;
import org.processmining.framework.log.LogReader;
import org.processmining.framework.log.ProcessInstance;

/**
 * Contains all the data necessary for the presentation tier. The data comes
 * from the event log.
 *
 * @author AA and CJ
 */
public class DataBean {

    private String pathToFile;
    private int numProcessInstances;
    private int numLogEvents;
    private int numTotalEvents;
    private int numOriginators;
    private boolean hasLoops;
    //Log Table
    private String[] logColumnNames;
    private String[][] logTableData = null;
    private int logTableDataRowCount = 0;
    //Log Browser
    private LogReader logReader;
    private List<ProcessInstance> instances;

    /**
     * Default constructor.
     */
    public DataBean() {
        //logTableData = new String[6][4]; //TODO agregar setColumnCount y setRowCount para el tamano del arreglo
    }

    /**
     * Creates the log table containing the event's log properties.
     *
     * @param rows
     * @param cols
     */
    public void createLogTableData(int rows, int cols) {
        logTableDataRowCount = 0;
        logTableData = new String[rows][cols];
    }

    /**
     * Set columns of the log table.
     *
     * @param names
     */
    public void setLogTableColumnNames(String[] names) {
        logColumnNames = names;
    }

    /**
     * Returns the log table columns.
     *
     * @return
     */
    public String[] getLogTableColumnNames() {
        return logColumnNames;
    }

    /**
     * Adds a row to the log table.
     *
     * @param row
     */
    public void addRowLogTableData(String[] row) {
        logTableData[logTableDataRowCount] = row;
        logTableDataRowCount += 1;
    }

    /**
     * Sets the content of a cell of the log table.
     *
     * @param col
     * @param row
     * @param value
     */
    public void setLogTableDataAt(int col, int row, String value) {
        if (logTableData == null) {
            System.out.println("Err Use setSizeLogTableData() before setting values");
            System.out.println("logTableData created with fix values: cols 4 rows 10 ");
        } else {
            logTableData[row][col] = value;
        }
    }

    /**
     * Concatenates the string value from the argument to the current value of
     * the cell.
     *
     * @param col
     * @param row
     * @param value
     */
    public void concatLogTableDataAt(int col, int row, String value) {
        logTableData[row][col] += value;
    }

    /**
     * Returns content at the given cell.
     *
     * @param col
     * @param row
     * @return
     */
    public String getLogTableDataAt(int col, int row) {
        return logTableData[row][col];
    }

    /**
     * Returns the log table.
     *
     * @return
     */
    public String[][] getLogTableData() {
        return logTableData;
    }

    /**
     * Sets the property path of event log.
     *
     * @param e
     */
    public void setPathToFile(String e) {
        this.pathToFile = e;
    }

    /**
     * Returns the property path of event log.
     *
     * @return
     */
    public String getPathToFile() {
        return this.pathToFile;
    }

    /**
     * Sets the property number of process instances in the event log.
     *
     * @param n
     */
    public void setNumProcessInstances(int n) {
        this.numProcessInstances = n;
    }

    /**
     * Returns the property number of process instances in the event log.
     *
     * @return
     */
    public int getNumProcessInstances() {
        return this.numProcessInstances;
    }

    /**
     * Sets the property number of events in the event log.
     *
     * @param n
     */
    public void setNumLogEvents(int n) {
        this.numLogEvents = n;
    }

    /**
     * Returns the property number of events in the event log.
     *
     * @return
     */
    public int getNumLogEvents() {
        return this.numLogEvents;
    }

    /**
     * Sets the property total number of events in the event log.
     *
     * @param n
     */
    public void setNumTotalEvents(int n) {
        numTotalEvents = n;
    }

    /**
     * Returns the property total number of events in the event log.
     *
     * @return
     */
    public int getNumTotalEvents() {
        return numTotalEvents;
    }

    /**
     * Sets the property number of originators in the event log.
     *
     * @param n
     */
    public void setnumOriginators(int n) {
        numOriginators = n;
    }

    /**
     * Returns the property number of originators in the event log.
     *
     * @return
     */
    public int getNumOriginators() {
        return numOriginators;
    }

    /**
     * Sets the log reader.
     *
     * @param lr
     */
    public void setLogReader(LogReader lr) {
        logReader = lr;
        instances = logReader.getInstances();
    }

    /**
     * Returns the log reader.
     *
     * @return
     */
    public LogReader getLogReader() {
        return logReader;
    }

    /**
     * Sets the property if event log contains loops.
     *
     * @return
     */
    public boolean hasLoops() {
        return hasLoops;
    }

    /**
     * Returns the property if event log contains loops.
     *
     * @param hasLoops
     */
    public void setHasLoops(boolean hasLoops) {
        this.hasLoops = hasLoops;
    }

    /**
     * Returns a list of the names of process instances.
     *
     * @return
     */
    public List<String> getInstances() {
        List<String> strInstances = new ArrayList<String>();
        if (logReader == null) {
        } else {
            for (int i = 0; i < instances.size(); i++) {
                strInstances.add(logReader.getInstance(i).getName());
            }
        }
        return strInstances;
    }

    /**
     * Returns a list of event names given the ID of a process instance.
     *
     * @param instanceID
     * @return
     */
    public List<String> getEventsFromInstance(String instanceID) {
        List<String> strEvents = new ArrayList<String>();
        AuditTrailEntryList events;
        ProcessInstance instance;

        try {
            for (int i = 0; i < instances.size(); i++) {
                instance = logReader.getInstance(i);
                if (instance.getName().equals(instanceID)) {
                    events = instance.getAuditTrailEntryList();
                    for (int j = 0; j < events.size(); j++) {
                        strEvents.add(String.valueOf(events.get(j).getName()));
                    }
                }
            }
        } catch (Exception e) {
        }
        return strEvents;
    }

    /**
     * Returns a list of list of attributes given the ID of a process instance
     * and the ID of the event. The first list used for the inputs, the second
     * for the outputs and the third for other attributes.
     *
     * @param instanceID
     * @param eventID
     * @return
     */
    public List<List<String>> getAttrFromEvent(String instanceID, String eventID) {
        //The first list used for the inputs, the second for the outputs and the third for other attributes
        List<List<String>> strAttributes = new ArrayList<List<String>>();
        AuditTrailEntryList events;
        AuditTrailEntry event;
        String eventName;
        Map<String, String> attributes;
        Set<String> keySet;
        String[] attrArray;
        String attrKey;

        strAttributes.add(new ArrayList<String>()); //Inputs
        strAttributes.add(new ArrayList<String>()); //Outputs
        strAttributes.add(new ArrayList<String>()); //Others
        try {
            for (int i = 0; i < instances.size(); i++) {
                if (logReader.getInstance(i).getName().equals(instanceID)) {
                    events = logReader.getInstance(i).getAuditTrailEntryList();
                    for (int j = 0; j < events.size(); j++) {
                        event = events.get(j);
                        eventName = event.getName();
                        if (eventName.equals(eventID)) {
                            attributes = event.getAttributes();
                            for (int k = 0; k < attributes.size(); k++) {
                                keySet = instances.get(i).getAuditTrailEntryList().get(j).getAttributes().keySet();
                                attrArray = (String[]) keySet.toArray(new String[keySet.size()]);
                                attrKey = attrArray[k];
                                if (attrKey.substring(0, 6).equals("Input_")) {
                                    strAttributes.get(0).add(attrKey.substring(6).toString());
                                } else if (attrKey.substring(0, 7).equals("Output_")) {
                                    strAttributes.get(1).add(attrKey.substring(7).toString());
                                } else {
                                    strAttributes.get(2).add(attrKey.toString());
                                }
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            //System.out.println(e.printStackTrace());
        }
        return strAttributes;
    }
//    public void initLogBrowser(){
//        mapInstanceEventKeys = new TreeMap<Integer,ArrayList<Integer>>();
//        instanceKeyValue = new HashMap<Integer,String>();
//        eventKeyValue = new HashMap<Integer, String>();
//        
//        mapEventAtrrInputKeys = new TreeMap<Integer, ArrayList<Integer>>();
//        mapEventAtrrOutputKeys = new TreeMap<Integer, ArrayList<Integer>>();
//        mapEventAtrrOtherKeys = new TreeMap<Integer, ArrayList<Integer>>();
//        attrInputKeyValue = new HashMap<Integer,String>();
//        attrOutputKeyValue = new HashMap<Integer,String>();
//        attrOtherKeyValue =  new HashMap<Integer,String>();
//        
//    }
//    
//    public void addInstanceKeyValue(int key,String instanceName){
//        instanceKeyValue.put(key, instanceName);
//    }
//    
//    public void addEventKeyValue(int key,String eventName){
//        eventKeyValue.put(key,eventName);
//    }
//    
//    public void addMapInstanceEventKeys(int instanceKey,ArrayList<Integer> eventKeys){
//        mapInstanceEventKeys.put(instanceKey, eventKeys);
//    }
//    public Map<Integer,String> getInstanceKeyValue(){
//        return instanceKeyValue;
//    }
//    public String getEventValue(int index){
//        if(eventKeyValue.containsKey(index)){
//            return eventKeyValue.get(index);
//        }else{
//            return "";
//        }
//    }
//    public Map<Integer,String> getEventKeyValues(){
//        return eventKeyValue;
//    }
//    public Map<Integer,ArrayList<Integer>> getMapInstanceEventKeys(){
//        return mapInstanceEventKeys;
//    }
//    
//    public void addAttrInputKeyValue(int index, String attrName){
//        attrInputKeyValue.put(index, attrName);
//    }
//    public void addAttrOutputKeyValue(int index, String attrName){
//        attrOutputKeyValue.put(index, attrName);
//    }
//    public void addAttrOtherKeyValue(int index, String attrName){
//        attrOtherKeyValue.put(index, attrName);
//    }
//    
//    public void addMapEventAttrInputKeys(int eventKey,ArrayList<Integer> attrKeys){
//        mapEventAtrrInputKeys.put(eventKey, attrKeys);
//    }
//    public Map<Integer,ArrayList<Integer>> getMapEventAtrrInputKeys(){
//        return mapEventAtrrInputKeys;
//    }
//    public void addMapEventAttrOutputKeys(int eventKey,ArrayList<Integer> attrKeys){
//        mapEventAtrrOutputKeys.put(eventKey, attrKeys);
//    }
//    public Map<Integer,ArrayList<Integer>> getMapEventAtrrKeys(){
//        return mapEventAtrrOutputKeys;
//    }
//    public void addMapEventAttrOtherKeys(int eventKey,ArrayList<Integer> attrKeys){
//        mapEventAtrrOtherKeys.put(eventKey, attrKeys);
//    }
//    public Map<Integer,ArrayList<Integer>> getMapEventAtrrOtherKeys(){
//        return mapEventAtrrOtherKeys;
//    }
//    public String getAttrInputValue(int index){
//        if (attrInputKeyValue.containsKey(index)){
//            return attrInputKeyValue.get(index);
//        }else{
//            return "";
//        }
//    }
//    public String getAttrOutputValue(int index){
//        if(attrOutputKeyValue.containsKey(index)){
//            return attrOutputKeyValue.get(index);
//        }else{
//            return "";
//        }
//    }
//    public String getAttrOtherValue(int index){
//        if(attrOtherKeyValue.containsKey(index)){
//            return attrOtherKeyValue.get(index);
//        }else{
//            return "";
//        }
//    }
}
